package com.gjy.util;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

/**
 * 简易文件服务器 Client 端
 * @author 宫静雨
 * @version 1.0
 * @datetime 2021-12-23 12:33:32
 */
public class FileUtil {

    private static final String CRLF = "\r\n";
    private static final String twoHyphens = "--";
    private static final String boundary = "*****";

    /**
     * 文件上传
     * @param actionUrl 文件上传 URL  http://localhost:8080/file/upload
     * @param uploadFilePaths 本地文件的绝对路径+文件名，这是一个数组，支持多个文件同时上传
     *        实例：{"D:/图片/2021-6-2-1.jpg"}
     * @return 文件上传生成的 UUID
     */
    public static String upload(String actionUrl, String[] uploadFilePaths) {
        DataOutputStream ds = null;
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        StringBuilder sb = new StringBuilder();

        try {
            // 包装一个 HttpURLConnection
            URL url = new URL(actionUrl);
            URLConnection urlConnection = url.openConnection();
            HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;

            // 设置相关参数
            httpURLConnection.setDoInput(true);
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setUseCaches(false);
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

            // 设置 DataOutputStream
            ds = new DataOutputStream(httpURLConnection.getOutputStream());
            for (String uploadFile : uploadFilePaths) {
                String filename = uploadFile.substring(uploadFile.lastIndexOf("/") + 1);
                ds.writeBytes(twoHyphens + boundary + CRLF);
                ds.writeBytes("Content-Disposition: form-data; " + "name=files" + ";filename=" + filename + CRLF);
                ds.writeBytes(CRLF);
                FileInputStream fStream = new FileInputStream(uploadFile);
                byte[] buffer = new byte[1024];
                int length;
                while ((length = fStream.read(buffer)) != -1) {
                    ds.write(buffer, 0, length);
                }
                ds.writeBytes(CRLF);
                fStream.close();
            }
            ds.writeBytes(twoHyphens + boundary + twoHyphens + CRLF);
            ds.flush();
            // 如果上传失败，抛出异常
            if (httpURLConnection.getResponseCode() >= 300) {
                throw new Exception("HTTP Request i not success, Response code is " + httpURLConnection.getResponseCode());
            }

            // 封装上传成功后的数据
            inputStream = httpURLConnection.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream);
            reader = new BufferedReader(inputStreamReader);
            String tempLine;
            while ((tempLine = reader.readLine()) != null) {
                sb.append(tempLine);
                sb.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (ds != null) {
                    ds.close();
                }
                if (reader != null) {
                    reader.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }

    /**
     * 下载文件
     * @param urlPath 服务器的地址，格式必须和示例一致：http://localhost:8080/file/get?uuid=
     * @param uuid 想要下载文件的 UUID，此UUID必须存在
     * @param name 给下载的文件起一个名字
     * @param type 待下载文件的类型
     * @param downloadPath 存放到那个目录
     * @return 返回下载后的文件的全路径
     */
    public static File get(String urlPath, String uuid,
                           String name, String type,String downloadPath) {
        File file = null;
        // 拼接一个有效的URL：http://localhost:8080/file/get?uuid=3e0ee4ee-e1f1-48ff-a1d2-1a08cbc9eeea
        String realPath = urlPath + uuid;
        try {
            URL url = new URL(realPath);
            URLConnection urlConnection = url.openConnection();
            HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;

            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            httpURLConnection.connect();

            BufferedInputStream bin = new BufferedInputStream(httpURLConnection.getInputStream());
            String path = downloadPath + name + "." + type; // 文件的全路径
            file = new File(path);
            FileOutputStream out = new FileOutputStream(file);
            int size;
            byte[] buf = new byte[1024];
            while ((size = bin.read(buf)) != -1) {
                out.write(buf, 0, size);
            }
            bin.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 获取文件的元数据信息
     * @param urlPath 服务器的地址，格式必须和示例一致：http://localhost:8080/file/get?uuid=
     * @param uuid 想要下载文件的 UUID，此UUID必须存在
     * @return 返回文件的元数据
     */
    public static String getInfo(String urlPath, String uuid) {
        String realPath = urlPath + uuid;
        StringBuilder sb = new StringBuilder();
        try {
            URL url = new URL(realPath);
            URLConnection urlConnection = url.openConnection();
            HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;

            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            httpURLConnection.connect();

            BufferedInputStream bin = new BufferedInputStream(httpURLConnection.getInputStream());
            InputStreamReader inputStreamReader = new InputStreamReader(bin);
            BufferedReader reader = new BufferedReader(inputStreamReader);
            String line ;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            bin.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
}
